# 链接：https://www.zybuluo.com/rianusr/note/1195225
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
data=pd.read_csv('ml-100k/u.data',sep='\t',names=['user_id','item_id','rating','timestamp'])
print('数据结构:\n',data.head())

# 数据信息查看
print(data.info())

# 数据描述
print('数据描述:\n',data.describe())

print('用户个数:',data.user_id.nunique())  # nunique() --> 返回不重复user_id的个数，统计用户的个数
print('商品个数:',data.item_id.nunique()) # 统计被评价电影的个数
print('用户商品重复个数:',data.duplicated(subset=['user_id','item_id']).sum())  # 查看user_id与item_id是否有重复的情况

# 拆分为训练集和测试集
# 3.将原数据集拆分成训练集和测试集
# 这里使用80%的数据做训练，20%的数据做测试
# 测试集和训练集必须是没有交集的
ratio = 0.8
offset = int(data.shape[0] * ratio)
train_data = data[:offset]

## 数据检查
# 统计每个物品对应的用户数
item_id_usercnt = train_data.groupby('item_id').count().user_id
print('统计每个物品对应的用户数:\n',item_id_usercnt[:5])
# 展示分类聚合结果
# plt.hist(item_id_usercnt.values)
# plt.show()
# 分别查看每一物品对应的用户的十分位数（十分位数、二十分位数...一百分位数）
print('分别查看每一物品对应的用户的十分位数:\n', item_id_usercnt.quantile(q=np.arange(0,1.1,0.1)))

# 统计每个用户对应的物品数
user_id_itemcnt = train_data.groupby('user_id').count().item_id
user_id_itemcnt[:5]
# 展示分类聚合结果
# plt.hist(user_id_itemcnt.values)
# plt.show()
# 分别查看每一用户对应的物品的十分位数（十分位数、二十分位数...一百分位数）
print('分别查看每一用户对应的物品的十分位数:\n', user_id_itemcnt.quantile(q=np.arange(0,1.1,0.1)))

## 构建用户-物品矩阵
# 通过nunique()方法分别获得user_id、item_id的去重计数
# 获取矩阵行数m、列数n
m_users = data.user_id.nunique()  #
n_items = data.item_id.nunique()

# 创建一个全是0的m*n的矩阵并向矩阵中填充对应数据
user_item_matrix = np.zeros((m_users,n_items))  # 创建一个全是0的m*n的矩阵
'''
itertuples() 将每一行转换为对应的元组，且数据一一对应
for line in data.head().itertuples():
    print(line)
>> Pandas(Index=0, user_id=196, item_id=242, rating=3, timestamp=881250949)
>> Pandas(Index=1, user_id=186, item_id=302, rating=3, timestamp=891717742)
>> Pandas(Index=2, user_id=22, item_id=377, rating=1, timestamp=878887116)
>> Pandas(Index=3, user_id=244, item_id=51, rating=2, timestamp=880606923)
>> Pandas(Index=4, user_id=166, item_id=346, rating=1, timestamp=886397596)
'''
for line in data.itertuples():
    user_item_matrix[line[1]-1,line[2]-1]=line[3]
    '''
    因为user_id 和 item_id 都是从1开始编号的，而矩阵的索引是从零开始
    data数据的第一列为user_id，第二列为item_id，第三列则为对应user对item的评分
    '''
print(user_item_matrix)    #展示一下用户物品矩阵
print("user_item_matrix.nonzero()[0]",user_item_matrix.nonzero()[0])
print("user_item_matrix.nonzero()[1]",user_item_matrix.nonzero()[1])
# 统计矩阵中非0值的个数与矩阵总元素个数的比值，保留3位小数
sparsity = round(len(user_item_matrix.nonzero()[0])/float(m_users*n_items),3)
print('矩阵稀疏性', sparsity)
# 用户-物品 矩阵非常稀疏，只有6%的用户物品有互动记录
